/*******************************************************************************
   @file    dev_I2c.h
   @author  H.M.Shim (elecage@gmail.com)
   @version 
   @date    2013. 7. 29.
   @brief   
  ******************************************************************************
  The MIT License (MIT)

Copyright (c) 2013 <copyright holders>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
  ******************************************************************************
  */



/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef DEV_I2C_H_
#define DEV_I2C_H_

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include "devio.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_i2c.h"
/* Exported typedef -----------------------------------------------------------*/

typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
typedef enum {I2C_SLAVE = 0 , I2C_MASTER = !I2C_SLAVE} I2CMSMode;

typedef struct _Dev_I2c_flag{
	int8_t 			stat;				/**< @brief 장치의 상태 플래그 */
	I2CMSMode 		ms;					/**< @brief 마스터이면 0, slave이면 0x0008 */
	int8_t		  	speedMode;		/**< @brief 장치의 스피드 모드 */
	int8_t			addressMode;		/**< @brief 장치의 어드레스 모드 */
	uint16_t 		address;			/**< @brief 읽고 쓰기를 할 주소 */
	uint32_t 		map;				/**< @brief I2C 슬레이브 내부 어드레스 */
	uint8_t			mapSize;			/**< @brief mapSize, 1, 2, 4 */
	int32_t		timeout;			/**< @brief 타임아웃 */
}__attribute__((packed))Dev_I2c_flag;


enum Dev_I2C_IOCTL_Param {
	DEV_I2C_SET_ADDR_MODE,				/**< @brief I2C 어드레스 모드 설정 */
	DEV_I2C_SET_ADDR,					/**< @brief I2C 읽기/쓰기 주소 선택 */
	DEV_I2C_SET_MAP_SIZE,				/**< @brief MAP의 크기 지정 */
	DEV_I2C_SET_MAP,					/**< @brief I2C 내부 어드레스 선택 */
	DEV_I2C_SET_SPEED,					/**< @brief I2C 클록 속도 설정 */
	DEV_I2C_SET_TIMEOUT,				/**< @brief I2C의 타임아웃 시간 설정 */
	DEV_I2C_SET_MASTER,					/**< @brief 장치를 I2C 마스터로 설정 */
	DEV_I2C_SET_SLAVE,					/**< @brief 장치를 I2C 슬레이브로 설정 */
	DEV_I2C_SET_ACK_MODE,				/**< @brief I2C acknowledge mode 1 : ack mode, 0 : nak mode*/

	DEV_I2C_GET_ADDR_MODE,				/**< @brief I2C 어드레스 모드를 가져오기 */
	DEV_I2C_GET_ADDR,					/**< @brief I2C 읽기/쓰기 주소  가져오기*/
	DEV_I2C_GET_MAP_SIZE,				/**< @brief MAP의 크기 지정 */
	DEV_I2C_GET_MAP,					/**< @brief I2C 내부 어드레스 확인 */
	DEV_I2C_GET_SPEED,					/**< @brief I2C 클록 속도  가져오기 */
	DEV_I2C_GET_TIMEOUT,				/**< @brief I2C의 타임아웃 시간 가져오기 */
	DEV_I2C_GET_MASTER,					/**< @brief 장치 I2C 마스터이면 1, 슬레이브이면 0 */
	DEV_I2C_GET_SLAVE,					/**< @brief 장치 I2C 슬레이브이면 1, 슬레이브이면 0 */
	DEV_I2C_CLEAR_BUSY,					/**< @brief busy 신호를 클리어한다. */
};

/* Exported constants --------------------------------------------------------*/
#define NUM_I2C 					3

#define I2C_FAST_SPEED 				340000
#define I2C_FAST_DUTYCYCLE			I2C_DutyCycle_16_9

#define I2C_DEFAULT_SPEED 			100000
#define I2C_DEFAULT_DUTYCYCLE		I2C_DutyCycle_2

/* Default Configuration Device */

/* I2C 1 */
#define I2C1_SDA_GPIO_CLK			RCC_AHB1Periph_GPIOB
#define I2C1_SDA_PIN				GPIO_Pin_7
#define I2C1_SDA_GPIO_PORT			GPIOB
#define I2C1_SDA_SOURCE				GPIO_PinSource7
/*
 * #define I2C1_SDA_GPIO_CLK			RCC_AHB1Periph_GPIOB
 * #define I2C1_SDA_PIN					GPIO_Pin_7
 * #define I2C1_SDA_GPIO_PORT			GPIOB
 * #define I2C1_SDA_SOURCE				GPIO_PinSource7
 */
#define I2C1_SDA_AF					GPIO_AF_I2C1

#define I2C1_SCL_GPIO_CLK			RCC_AHB1Periph_GPIOB
#define I2C1_SCL_PIN				GPIO_Pin_6
#define I2C1_SCL_GPIO_PORT			GPIOB
#define I2C1_SCL_SOURCE				GPIO_PinSource6
/*
 * #define I2C1_SCL_GPIO_CLK			RCC_AHB1Periph_GPIOB
 * #define I2C1_SCL_PIN					GPIO_Pin_8
 * #define I2C1_SCL_GPIO_PORT			GPIOB
 * #define I2C1_SCL_SOURCE				GPIO_PinSource8
 */
#define I2C1_SCL_AF					GPIO_AF_I2C1

/* I2C 2 */
#define I2C2_SDA_GPIO_CLK			RCC_AHB1Periph_GPIOF
#define I2C2_SDA_PIN				GPIO_Pin_0
#define I2C2_SDA_GPIO_PORT			GPIOF
#define I2C2_SDA_SOURCE				GPIO_PinSource0
/*
 * #define I2C2_SDA_GPIO_CLK			RCC_AHB1Periph_GPIOH
 * #define I2C2_SDA_PIN					GPIO_Pin_5
 * #define I2C2_SDA_GPIO_PORT			GPIOH
 * #define I2C2_SDA_SOURCE				GPIO_PinSource5
 */
#define I2C2_SDA_AF					GPIO_AF_I2C2

/*
 * #define I2C2_SDA_GPIO_CLK			RCC_AHB1Periph_GPIOB
 * #define I2C2_SDA_PIN					GPIO_Pin_11
 * #define I2C2_SDA_GPIO_PORT			GPIOB
 * #define I2C2_SDA_SOURCE				GPIO_PinSource11
 */

#define I2C2_SCL_GPIO_CLK			RCC_AHB1Periph_GPIOF
#define I2C2_SCL_PIN				GPIO_Pin_1
#define I2C2_SCL_GPIO_PORT			GPIOF
#define I2C2_SCL_SOURCE				GPIO_PinSource1
/*
 * #define I2C2_SCL_GPIO_CLK			RCC_AHB1Periph_GPIOH
 * #define I2C2_SCL_PIN					GPIO_Pin_4
 * #define I2C2_SCL_GPIO_PORT			GPIOH
 * #define I2C2_SCL_SOURCE				GPIO_PinSource4
 */
/*
 * #define I2C2_SCL_GPIO_CLK			RCC_AHB1Periph_GPIOB
 * #define I2C2_SCL_PIN					GPIO_Pin_10
 * #define I2C2_SCL_GPIO_PORT			GPIOB
 * #define I2C2_SCL_SOURCE				GPIO_PinSource10
 */

#define I2C2_SCL_AF					GPIO_AF_I2C2

/* I2C 3 */
#define I2C3_SDA_GPIO_CLK			RCC_AHB1Periph_GPIOH
#define I2C3_SDA_PIN				GPIO_Pin_8
#define I2C3_SDA_GPIO_PORT			GPIOH
#define I2C3_SDA_SOURCE				GPIO_PinSource8
/*
 * #define I2C3_SDA_GPIO_CLK			RCC_AHB1Periph_GPIOC
 * #define I2C3_SDA_PIN					GPIO_Pin_9
 * #define I2C3_SDA_GPIO_PORT			GPIOC
 * #define I2C3_SDA_SOURCE				GPIO_PinSource9
 */
#define I2C3_SDA_AF					GPIO_AF_I2C3

#define I2C3_SCL_GPIO_CLK			RCC_AHB1Periph_GPIOA
#define I2C3_SCL_PIN				GPIO_Pin_8
#define I2C3_SCL_GPIO_PORT			GPIOA
#define I2C3_SCL_SOURCE				GPIO_PinSource8

#define I2C3_SCL_AF					GPIO_AF_I2C3


#define I2C_OWN_ADDRESS				0x00

#define DEV_FLAG_I2C_10BITS_ADDRESS	0x0001
#define DEV_FLAG_I2C_7BITS_ADDRESS	0x0002
#define DEV_FLAG_I2C_FAST_MODE		0x0004
#define DEV_FLAG_I2C_SLAVE			0x0008
#define DEV_FLAG_MAP_SIZE_1			0x0010
#define DEV_FLAG_MAP_SIZE_2			0x0020
#define DEV_FLAG_MAP_SIZE_4			0x0040

#define DEV_ARG_I2C_ADDRESS_10BIT	((const char*)"10bit_mode")
#define DEV_ARG_I2C_ADDRESS_7BIT	((const char*)"7bit_mode")
#define DEV_ARG_I2C_SPEED_FAST		((const char*)"fast_mode")
#define DEV_ARG_I2C_SPEED_NORMAL	((const char*)"normal_mode")
#define DEV_ARG_I2C_MAP_SIZE_1		((const char*)"map_1byte")
#define DEV_ARG_I2C_MAP_SIZE_2		((const char*)"map_2byte")
#define DEV_ARG_I2C_MAP_SIZE_4		((const char*)"map_4byte")

#define DEV_ARG_I2C_SET_ADDRESS		((const char*)"set_address")
#define DEV_ARG_I2C_GET_ADDRESS		((const char*)"get_address")
#define DEV_ARG_I2C_SET_MAP			((const char*)"set_map")
#define DEV_ARG_I2C_GET_MAP			((const char*)"get_map")
#define DEV_ARG_I2C_SET_MAP_SIZE	((const char*)"set_mapsize")
#define DEV_ARG_I2C_GET_MAP_SIZE	((const char*)"get_mapsize")
#define DEV_ARG_I2C_SET_MASTER		((const char*)"set_master")
#define DEV_ARG_I2C_SET_SLAVE		((const char*)"set_slave")
#define DEV_ARG_I2C_GET_MS			((const char*)"get_ms")
#define DEV_ARG_I2C_CLEAR_BUSY		((const char*)"clear_busy")
#define MAX_I2C_BUF					128

/* Exported macro ------------------------------------------------------------*/

/* Exported variables ------------------------------------------------------- */
extern InterruptHandleFunc i2cIsrEvFunc[NUM_I2C];
extern InterruptHandleFunc i2cIsrErFunc[NUM_I2C];
/* Exported functions ------------------------------------------------------- */
int32_t registerDev_I2c(void);
int32_t dev_I2cOpen(const int8_t* devname, int32_t flags);
ssize_t dev_I2cWrite(int32_t dd, const void *buf, size_t n);
ssize_t	dev_I2cRead(int32_t dd, void *buf, size_t nbytes);
ssize_t dev_I2cIoctl(int32_t dd, int32_t request, void* data);
int32_t dev_I2cClose(int32_t dd);

void dev_I2cConfigInt(uint8_t portsource, EXTI_Config* config);

#ifdef USE_CMDLINE
int32_t dev_I2cOpenCmd(int32_t argc, int8_t *argv[]);
int32_t dev_I2cReadCmd(int32_t argc, int8_t *argv[]);
int32_t dev_I2cWriteCmd(int32_t argc, int8_t *argv[]);
int32_t dev_I2cIoctlCmd(int32_t argc, int8_t *argv[]);
int32_t dev_I2cCloseCmd(int32_t argc, int8_t *argv[]);
#endif /*USE_CMDLINE */
#endif /* DEV_I2C_H_ */
